﻿/***
    Copyright 2012 Stijn Van Antwerpen

    This file is part of Qasparov.

    Qasparov is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Qasparov is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Qasparov. If not, see <http://www.gnu.org/licenses/>.

 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using E = Com.Oxilly.Qsb.Core.SDK.Events;
using System.Threading;
using System.Configuration;
using Com.Oxilly.Qsb.Core.SDK.API;
using Com.Oxilly.Qsb.Core.Managers;
using Com.Oxilly.Qsb.Core.SDK.Events;

namespace Com.Oxilly.Qsb.Core
{
    public class Engine : Com.Oxilly.Qsb.Core.IEngine
    {

        #region State

        //internal StateManager.States State { get { return stateManager.State ; } }

        #endregion

        #region Events

        //TODO: Implments fire
        internal event EventHandler<E.QsbEventArgs> OnQsbEvent;
        public event EventHandler<E.QsbMessagePublished> OnQsbMessagePublished;

        #endregion

        #region Logging

        public void Log(String msg, SourceLevels level = SourceLevels.Verbose)
        {
            logManager.Log(msg, level);
        }

        public void Log(E.LogEventArgs log)
        {
            logManager.Log(log);
        }

        #endregion

        #region Properties
        private SDK.QsbEngineApi api;
        public SDK.QsbEngineApi Api { get { return api; } }
              
        private LogManager logManager; 
        private StateManager stateManager;
        //private StateChangeHandler stateChangeHandler;
        private ExtensionManager extensionLManager;

        #endregion

        #region Constructor
        public Engine()
        {
            api = new SDK.QsbEngineApi(this);
            stateManager = RegisterManager(new StateManager(this));
            logManager = RegisterManager(new LogManager());
            extensionLManager = RegisterManager(new ExtensionManager(this));

            //stateChangeHandler = new StateChangeHandler(this);
            //stateManager.OnStateChanges += stateChangeHandler.OnStateChanges; 
            //this.OnStateChanges += new EventHandler<E.StateChangedEventArgs>(HandelOnStateChanges);
        }
        internal List<ManagerBase> managers = new List<ManagerBase>();

        internal T RegisterManager<T>(T manager) where T : ManagerBase
        {
            managers.Add(manager);
            return manager;
        }
        #endregion

       
        public void ProcessQsbCommand(QsbCommand command)
        {
            //if (this.stateManager.State == EngineStates.Running)
            //{
                command.Execute(this.Api);
            //}
            //else 
            //{
            //    throw new QsbException("Engine not ready to process QsbCommand");
            //}
        }

        public void ProcessQsbMessage(QsbMessage msg)
        {
            if (OnQsbMessagePublished != null)
            {
                OnQsbMessagePublished(this, new QsbMessagePublished(msg));
            }
            //Use the QAppManger to let all QApps process the message
            //TODO: maybe the QAppManager shouls just use the OnQsbMessagePublishedEvent
            this.extensionLManager.ProcessMessage(msg);            
        }



        public void Start()
        {
            Log("Scan for QApps started");
            this.extensionLManager.ScanForExtensions();
            Log("Scan for QApps completed");
            this.extensionLManager.StartUp();
        }

        public void Halt()
        {
            foreach (var m in this.managers)
            {
                m.ReleaseResources();
            }
            this.managers.Clear();
        }
    }
}
